package com.xiaoge.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoge.auth.JWTToken;
import com.xiaoge.bean.ActiveUser;
import com.xiaoge.converter.MenuConverter;
import com.xiaoge.entity.*;
import com.xiaoge.enums.UserStatusEnum;
import com.xiaoge.enums.UserTypeEnum;
import com.xiaoge.exception.BusinessException;
import com.xiaoge.mapper.*;
import com.xiaoge.response.ResultCode;
import com.xiaoge.service.UserService;
import com.xiaoge.utils.JWTUtils;
import com.xiaoge.utils.MD5Utils;
import com.xiaoge.utils.MenuTreeBuilder;
import com.xiaoge.vo.MenuNodeVO;
import com.xiaoge.vo.UserInfoVO;
import com.xiaoge.vo.UserVO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author XiaoGe
 * @since 2022-05-28
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Override
    public Page<User> getUserByPage(Page<User> page, UserVO userVO) {

        List<User> userList = this.baseMapper.getUserList(page, userVO);
        //将刚刚动态sql查询的内容给page对象,让它去实现分页
        page.setRecords(userList);
        return page;
    }

    @Override
    public String login(String username, String password) {
        String token;
        User user = this.baseMapper.getUserByUsername(username);
        if(user==null){
            throw new BusinessException(ResultCode.USER_ACCOUNT_NOT_EXIST.getCode(),
                    ResultCode.USER_ACCOUNT_NOT_EXIST.getMessage());
        }
        //获取数据库中加密的密码
        String encryptPassword = user.getPassword();
        //获取数据库中的盐
        String salt = user.getSalt();
        //将前端传过来的密码进行加密
        String target = MD5Utils.md5Encryption(password, salt);
        if(!target.equals(encryptPassword)){
            throw new BusinessException(ResultCode.USER_CREDENTIALS_ERROR.getCode(),
                    ResultCode.USER_CREDENTIALS_ERROR.getMessage());
        }
        //生成Token
        token = JWTUtils.sign(username, target);

        //登录成功之后需要将登录的状态存储在shiro
        JWTToken jwtToken = new JWTToken(token);
        try {
            SecurityUtils.getSubject().login(jwtToken);
        } catch (AuthenticationException e) {
            throw new BusinessException(e.getMessage());
        }
        return token;
    }

    @Override
    public User getUserByUsername(String username) {
        return this.baseMapper.getUserByUsername(username);
    }

    @Override
    public List<Role> findRolesById(Long id) {
        User dbUser = userMapper.selectById(id);
        if(dbUser==null){
            throw new BusinessException("该用户不存在");
        }
        List<Role> roles=new ArrayList<>();
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,dbUser.getId());
        List<UserRole> userRoleList = userRoleMapper.selectList(wrapper);
        List<Long> rids=new ArrayList<>();
        if(!CollectionUtils.isEmpty(userRoleList)){
            for (UserRole userRole : userRoleList) {
                rids.add(userRole.getRoleId());
            }
            if(!CollectionUtils.isEmpty(rids)){
                for (Long rid : rids) {
                    Role role = roleMapper.selectById(rid);
                    if(role!=null){
                        roles.add(role);
                    }
                }
            }
        }
        return roles;
    }

    @Override
    public List<Menu> findMenuByRoles(List<Role> roles) {
        List<Menu> menus=new ArrayList<>();
        if(!CollectionUtils.isEmpty(roles)){
            Set<Long> menuIds=new HashSet<>();//存放用户的菜单id
            List<RoleMenu> roleMenus;
            for (Role role : roles) {
                //根据角色ID查询权限ID
                LambdaQueryWrapper<RoleMenu> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(RoleMenu::getRoleId,role.getId());
                roleMenus= roleMenuMapper.selectList(wrapper);
                if(!CollectionUtils.isEmpty(roleMenus)){
                    for (RoleMenu roleMenu : roleMenus) {
                        menuIds.add(roleMenu.getMenuId());
                    }
                }
            }
            if(!CollectionUtils.isEmpty(menuIds)){
                for (Long menuId : menuIds) {
                    //该用户所有的菜单
                    Menu menu = menuMapper.selectById(menuId);
                    if(menu!=null){
                        menus.add(menu);
                    }
                }
            }
        }
        return menus;
    }

    /**
     * 添加用户
     * @param user
     */
    @Transactional
    @Override
    public void add(User user) {
        String username = user.getUsername();
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername,username);
        Long i = userMapper.selectCount(wrapper);
        if(i!=0){
            throw new BusinessException("该用户名已被占用");
        }
        String salt=UUID.randomUUID().toString().substring(0,32);
        user.setPassword(MD5Utils.md5Encryption(user.getPassword(), salt));
        user.setModifiedTime(new Date());
        user.setCreateTime(new Date());
        user.setSalt(salt);
        user.setType(UserTypeEnum.SYSTEM_USER.getTypeCode());//添加的用户默认是普通用户
        user.setStatus(UserStatusEnum.AVAILABLE.getStatusCode());//添加的用户默认启用
        user.setAvatar("http://badidol.com/uploads/images/avatars/201910/24/18_1571921832_HG9E55x9NY.jpg");
        userMapper.insert(user);
    }

    /**
     * 用户详情
     *
     * @return
     */
    @Override
    public UserInfoVO info() {
        ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
        System.out.println("----------------------------------------------");
        System.out.println(activeUser.toString());
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setAvatar(activeUser.getUser().getAvatar());
        userInfoVO.setUsername(activeUser.getUser().getUsername());
        userInfoVO.setUrl(activeUser.getUrls());
        userInfoVO.setNickname(activeUser.getUser().getNickname());
        List<String> roleNames = activeUser.getRoles().stream().map(Role::getRoleName).collect(Collectors.toList());
        userInfoVO.setRoles(roleNames);
        userInfoVO.setPerms(activeUser.getPermissions());
        userInfoVO.setIsAdmin(activeUser.getUser().getType()==UserTypeEnum.SYSTEM_ADMIN.getTypeCode());
        return userInfoVO;
    }

    @Override
    public void updateUser(User user) {
        user.setPassword(MD5Utils.md5Encryption(user.getPassword(), user.getSalt()));
        userMapper.updateById(user);
    }

    /**
     * 用户拥有的角色ID
     * @param id 用户id
     * @return
     */
    @Transactional
    @Override
    public List<Long> roles(Long id) {
        User user = userMapper.selectById(id);
        if(user==null){
            throw new BusinessException("该用户不存在");
        }
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,user.getId());
        List<UserRole> userRoleList = userRoleMapper.selectList(wrapper);
        List<Long> roleIds=new ArrayList<>();
        if(!CollectionUtils.isEmpty(userRoleList)){
            for (UserRole userRole : userRoleList) {
                Role role = roleMapper.selectById(userRole.getRoleId());
                if(role!=null){
                    roleIds.add(role.getId());
                }
            }
        }
        return roleIds;
    }

    /**
     * 分配角色
     * @param id 用户id
     * @param rids 角色数组
     */
    @Override
    @Transactional
    public void assignRoles(Long id, Long[] rids) {
        //删除之前用户的所有角色
        User user = userMapper.selectById(id);
        if(user==null){
            throw new BusinessException("用户不存在");
        }
        //删除之前分配的
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,user.getId());
        userRoleMapper.delete(wrapper);
        //增加现在分配的
        if(rids.length>0){
            for (Long rid : rids) {
                Role role = roleMapper.selectById(rid);
                if(role==null){
                    throw new BusinessException("roleId="+rid+",该角色不存在");
                }
                //判断角色状态
                if(role.getStatus()==0){
                    throw new BusinessException("roleName="+role.getRoleName()+",该角色已禁用");
                }
                UserRole userRole = new UserRole();
                userRole.setUserId(id);
                userRole.setRoleId(rid);
                userRoleMapper.insert(userRole);
            }
        }
    }

    /**
     * 功能描述: <br>
     * 〈根据用户id修改用户状态〉
     * @Param: [id, status]
     * @Return: void
     * @Author: Mr.Nie
     * @Date: 2022/6/13 14:37
     */
    @Override
    public void updateStatus(Long id, Boolean status) {
        User user = userMapper.selectById(id);
        if(user==null){
            throw new BusinessException("要更新状态的用户不存在");
        }
        ActiveUser activeUser= (ActiveUser) SecurityUtils.getSubject().getPrincipal();
        if(user.getId().equals(activeUser.getUser().getId())){
            throw new BusinessException(ResultCode.DO_NOT_ALLOW_TO_DISABLE_THE_CURRENT_USER.getCode(),
                    ResultCode.DO_NOT_ALLOW_TO_DISABLE_THE_CURRENT_USER.getMessage());
        }else {
            User t = new User();
            t.setId(id);
            t.setStatus(status? UserStatusEnum.DISABLE.getStatusCode() :
                    UserStatusEnum.AVAILABLE.getStatusCode());
            userMapper.updateById(t);
        }
    }

    @Override
    public List<MenuNodeVO> getMenu() {
        List<Menu> menus=null;
        List<MenuNodeVO> menuNodeVOS=new ArrayList<>();
        ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
        if(activeUser.getUser().getType()==UserTypeEnum.SYSTEM_ADMIN.getTypeCode()){
            //超级管理员
            menus=menuMapper.selectList(null);
        }else if(activeUser.getUser().getType()== UserTypeEnum.SYSTEM_USER.getTypeCode()){
            //普通系统用户
            menus= activeUser.getMenus();
        }
        if(!CollectionUtils.isEmpty(menus)){
            menuNodeVOS= MenuConverter.converterToMenuNodeVO(menus);
        }
        //构建树形菜单
        return MenuTreeBuilder.build(menuNodeVOS);
    }
}
